Exploiting path delimiters for web cache deception
Web cache deception con delimitadores de path: ; convierte /my-account en un asset estático .js para la caché mientras el origin sigue sirviendo la página de cuenta, cacheando la API key de carlos.
Target Overview & Vulnerability Summary
El objetivo es obtener la API key de carlos. El origin server trata ; como un delimitador de path: /my-account;wcd.js resuelve a /my-account. El cache server, en cambio, clasifica la URL por su terminación .js (extensión de asset estático) y decide cachearla. La respuesta de la página de cuenta queda almacenada bajo la clave con ;wcd.js.
| Campo | Valor |
|---|---|
| Severidad | Alta (exfiltración de datos autenticados vía caché pública) |
| Endpoint vulnerable | /my-account (cacheado bajo /my-account;wcd.js) |
| Root cause | Delimitador de path ; ignorado por la caché + cacheabilidad por extensión .js |
Credenciales del laboratorio: wiener:peter. Se dispone de una lista de caracteres delimitadores.
Technical Breakdown & Exploitation Flow
1. Confirmación del delimitador
Probando con el delimitador ;:
/my-account;asdf.js
La respuesta sigue conteniendo la información del perfil (el origin ignora ;asdf.js y sirve /my-account), y se observa que la respuesta se cachea (extensión .js → asset estático para la caché).
2. Construcción del exploit
Se prepara un script para el exploit server que fuerza al usuario a navegar a la URL deceptiva:
<script>
document.location = "https://0a6600ff0370fa4e80a9bc0000af0046.web-security-academy.net/my-account;wcd.js"
</script>
3. Resultado
carlosvisita el exploit server y su navegador navega a/my-account;wcd.js.- El origin sirve
/my-account(su página de cuenta con la API key). - La caché guarda la respuesta bajo la clave
/my-account;wcd.jspor su extensión.js. - El atacante solicita esa misma URL: la siguiente request a
/my-account;wcd.jsdevuelve el perfil cacheado decarloscon su API key.
Root Cause Analysis
El origin server acepta ; como delimitador de parámetros de ruta (RFC 3986 los define como path parameters), de modo que el recurso efectivo es /my-account. El cache server ignora esa semántica y decide la cacheabilidad por la extensión final de la cadena completa: .js. La misma URL es una página dinámica para la app y un asset estático para la caché. El delimitador se convierte en el mecanismo para insertar una extensión estática en una ruta dinámica.
Secure Remediation
- Rechazar o manejar explícitamente los parámetros de ruta (
;) en los endpoints dinámicos:/my-account;*no debe resolver a/my-account. - Configurar la caché para decidir cacheabilidad después de aplicar la misma semántica de path que el origin (sin contar parámetros de ruta para la extensión).
- Cachear solo extensiones de assets reales servidas por la app (lista blanca de extensiones + tipo de contenido) y nunca respuestas que incluyan cookies de sesión.
- Añadir
Cache-Control: private, no-storeen páginas de cuenta y endpoints autenticados.